package cn.demoncat.util.io;

import cn.demoncat.util.exception.IoRuntimeException;
import cn.demoncat.util.exception.ParamRuntimeException;
import cn.demoncat.util.lang.ParamEmptyUtil;
import cn.demoncat.util.web.ServletUtil;
import cn.demoncat.util.web.UrlUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;

/**
 * 文件下载(SpringMVC原生)
 * 
 * @author 延晓磊
 *
 * @since 2016年6月3日
 */
public final class FileDownloadUtil {
 
	/**
	 * 下载文件到Response
	 * 
	 * @param response
	 * @param filePath 	文件路径（本地文件）
	 * @param fileName 	文件下载的显示名称
	 * @param type	   	是否匹配MIME类型
	 */
	public static void downloadFile(HttpServletResponse response, String filePath, String fileName, boolean type){
		// 获取Response输出流
		OutputStream out = ServletUtil.getDownloadOut(response, fileName, type);
		try {
			//读取本地文件，通过NIO输出(关闭本地in，不关闭外部out)
			NioUtil.copy(new FileInputStream(filePath), out);
		} catch (IOException e) {
			throw new IoRuntimeException("下载文件失败", e);
		} finally {
			//释放资源
			CloseUtil.close(out);
		}
	}
	
	/**
	 * 通过URL抓取远程文件到本地
	 * 
	 * @param url 远程下载地址
	 * @param filePath 本地存放路径
	 */
	public static void wgetUrl(String url, String filePath){
		//参数校验
		if (ParamEmptyUtil.isBlank(url,filePath)) {
			throw ParamRuntimeException.NULL; 
		}
		//创建URL
		URL u = UrlUtil.getUrl(url);
		URLConnection conn = null;
		InputStream in = null;
		try {
			//打开URL连接
			conn = u.openConnection();
			//获取URL连接的输入流
			in = conn.getInputStream();
			//使用NIO输出到本地(不关闭外部输入流，关闭本地输出流)
			NioUtil.copy(in, new FileOutputStream(filePath));
		} catch (IOException e) {
			throw new IoRuntimeException("通过URL远程下载文件失败", e);
		} finally {
			//释放资源
			CloseUtil.close(in);
			CloseUtil.close(conn);
		}
	}
	
	/**
	 * 通过URL抓取远程文件到本地
	 * 
	 * @param url 远程下载地址
	 * @param dirPath 本地存放目录路径，以/结尾
	 * 
	 */
	public static void wgetUrlToDir(String url, String dirPath){
		//参数校验
		if (ParamEmptyUtil.isBlank(url,dirPath)) {
			throw ParamRuntimeException.NULL; 
		}
		//创建URL
		URL u = UrlUtil.getUrl(url);
		URLConnection conn = null;
		InputStream in = null;
		try {
			//打开URL连接
			conn = u.openConnection();
			//获取URL连接的输入流
			in = conn.getInputStream();
			//使用NIO输出到本地(不关闭外部输入流，关闭本地输出流)
			NioUtil.copy(in, new FileOutputStream(dirPath + url.substring(url.lastIndexOf('/')+1)));
		} catch (IOException e) {
			throw new IoRuntimeException("通过URL远程下载文件失败", e);
		} finally {
			//释放资源
			CloseUtil.close(in);
			CloseUtil.close(conn);
		}
	}
	
	/**
	 * 通过URL抓取远程文件并下载到Response
	 * 
	 * @param response
	 * @param url 		远程下载地址
	 * @param fileName 	文件下载的显示名称
	 * @param type		是否匹配MIME类型
	 */
	public static void downloadUrl(HttpServletResponse response, String url, String fileName, boolean type){
		//创建URL
		URL u = UrlUtil.getUrl(url);
		URLConnection conn = null;
		InputStream in;
		//获取Response输出流
		OutputStream out = ServletUtil.getDownloadOut(response, fileName, type);
		try {
			//打开URL连接
			conn = u.openConnection();
			//获取URL连接的输入流
			in = conn.getInputStream();
			//输出数据(2G以下/以上，内部实现缓存)
			if (FileSizeUtil.size(in) < 2000000000) {
				IoUtil.copy(in, out);
			}else{
				IoUtil.copyBig(in, out);
			}
		} catch (IOException e) {
			throw new IoRuntimeException("通过URL抓取远程文件并下载失败："+ e.getMessage(), e);
		} finally {
			//释放资源
			CloseUtil.close(conn);
		}
	}
	
}
